package cn.abcsys.cloud.devops.runtime.service.impl;

import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import cn.abcsys.cloud.devops.runtime.bean.GridBean;
import cn.abcsys.cloud.devops.runtime.bean.Result;
import cn.abcsys.cloud.devops.runtime.common.Common;
import cn.abcsys.cloud.devops.runtime.common.Constant;
import cn.abcsys.cloud.devops.runtime.common.Status;
import cn.abcsys.cloud.devops.runtime.common.SystemConfig;
import cn.abcsys.cloud.devops.runtime.common.Type;
import cn.abcsys.cloud.devops.runtime.core.HostCore;
import cn.abcsys.cloud.devops.runtime.dao.ClusterMapper;
import cn.abcsys.cloud.devops.runtime.dao.EventMapper;
import cn.abcsys.cloud.devops.runtime.dao.HostMapper;
import cn.abcsys.cloud.devops.runtime.dao.RegistryMapper;
import cn.abcsys.cloud.devops.runtime.entity.Cluster;
import cn.abcsys.cloud.devops.runtime.entity.Event;
import cn.abcsys.cloud.devops.runtime.entity.Host;
import cn.abcsys.cloud.devops.runtime.entity.Registry;
import cn.abcsys.cloud.devops.runtime.model.HostModel;
import cn.abcsys.cloud.devops.runtime.service.HostService;
/**
 * @author mayunhao
 * 主机管理
 */
@Component
public class HostServiceImpl implements HostService {
	private static final Logger LOGGER = Logger.getLogger(HostServiceImpl.class);
	@Autowired
	private HostMapper hostMapper;
	@Autowired
	private HostCore hostCore;
	@Autowired
	private ClusterMapper clusterMapper;
	@Autowired
	private SystemConfig systemConfig;
	@Autowired
	private RegistryMapper registryMapper;
	@Autowired
	private EventMapper eventMapper;
	@Override
	public Result createHost(Host host) {
		Result result = new Result(true, "创建主机成功");
		if(isHostExist(host.getHostIp())){
			return new Result(false, "主机["+host.getHostIp()+"]已存在");
		}
		try {
			Result hostInfo = null;
			if(host.getHostType()==Type.HOST.REGISTRY.ordinal()){
				hostInfo = hostCore.isDistribution(host.getHostIp());
			}else if(host.getHostType()==Type.HOST.MASTER.ordinal()
					||host.getHostType()==Type.HOST.NODE.ordinal()){
				hostInfo = hostCore.isKube(host.getHostIp());
			}
			if(null!=hostInfo&&hostInfo.isSuccess()){
				JSONObject jsonObject = (JSONObject)hostInfo.getData();
				host.setHostRealName(jsonObject.getString("Hostname"));
				host.setHostKernelVersion(jsonObject.getString("Kernel"));
				host.setHostBoot(jsonObject.getDate("Boot"));
				host.setHostOs(jsonObject.getString("OS"));
				//取内存
				JSONArray memArray = jsonObject.getJSONArray("Memory");
				if(null!=memArray.getJSONObject(0)&&
						!StringUtils.isEmpty(memArray.getJSONObject(0).getString("MemTotal"))){
					String memkB = memArray.getJSONObject(0).getString("MemTotal").replace("kB", "").trim();
					host.setHostMem(Integer.parseInt(memkB)/1024/1024);
				}
				//取cpu
				JSONArray cpuArray = jsonObject.getJSONArray("CPU");
				if(null!=cpuArray.getJSONObject(0)&&
						!StringUtils.isEmpty(cpuArray.getJSONObject(0).getString("CPU(s)"))){
					String cpus = cpuArray.getJSONObject(0).getString("CPU(s)").trim();
					host.setHostCpu(Integer.parseInt(cpus));
				}
				//取docker版本
				JSONArray runtimeArray = jsonObject.getJSONArray("Runtime");
				if(null!=runtimeArray.getJSONObject(0)){
					String dockerversion = runtimeArray.getJSONObject(0).getString("docker");
					host.setDockerVersion(dockerversion);
					String kubeVersion = runtimeArray.getJSONObject(0).getString("kubernetes");
					host.setKubeVersion(kubeVersion);
					String registryVersion = runtimeArray.getJSONObject(0).getString("distribution");
					host.setRegistryVersion(registryVersion);
				}
				//取network版本
				JSONArray networkArray = jsonObject.getJSONArray("Network");
				Iterator<Object> iterator = networkArray.iterator();
//				JSONArray networkArray = new JSONArray();
				while(iterator.hasNext()){
					JSONObject object = (JSONObject)iterator.next();
					String network_name = object.getString("name");
					if((network_name.startsWith("cali")
							||network_name.startsWith("lo")
							||network_name.startsWith("veth")||network_name.startsWith("docker"))&&!network_name.equals("docker0")){
						iterator.remove();
					}else{
						if(network_name.contains("@")){
							object.put("name", network_name.substring(0,network_name.indexOf("@")));
						}
					}
					
				}
				host.setNetwork(networkArray.toJSONString());
			}else{
				return hostInfo;
			}
			int issuccess = hostMapper.insertHost(host);
			if(issuccess!=1){
				result = new Result(false, "创建主机失败,原因未知");
			}
		} catch (SQLException e) {
			LOGGER.error("创建主机失败:"+e.getMessage());
			result = new Result(false, "创建主机失败："+e.getMessage());
		}
		LOGGER.info("创建成功");
		return result;
	}

	@Override
	public Result updateHost(Host host) {
		Result result = new Result(true, "更新主机成功");
		try {
			int issuccess = hostMapper.updateHost(host);
			if(issuccess!=1){
				result = new Result(false, "更新主机失败,原因未知");
			}
		} catch (SQLException e) {
			LOGGER.error("更新主机失败:"+e.getMessage());
			result = new Result(false, "更新主机失败："+e.getMessage());
		}
		return result;
	}

	@Override
	public Result deleteHost(Integer hostId) {
		Result result = new Result(true, "移除主机成功");
		try {
			Host host = hostMapper.getHostDetail(hostId);
			if(null!=host.getClusterId()){
				return new Result(false, "主机在运行集群环境中，请先从集群中移除");
			}
			int issuccess = hostMapper.deleteHost(hostId);
			if(issuccess!=1){
				result = new Result(false, "移除主机失败,原因未知");
			}
		} catch (SQLException e) {
			LOGGER.error("移除主机失败:"+e.getMessage());
			result = new Result(false, "移除主机失败："+e.getMessage());
		}
		return result;
	}

	@Override
	public Result getHostDetail(Integer hostId) {
		Result result = null;
		try {
			Host host = hostMapper.getHostDetail(hostId);
			if(null!=host){
				result = new Result(true,JSONObject.toJSON(host),"success");
			}else{
				result = new Result(false,"未查到相关结果");
			}
		} catch (SQLException e) {
			LOGGER.error("查询主机详情失败:"+e.getMessage());
			result = new Result(false, "查询失败："+e.getMessage());
		}
		return result;
	}

	@Override
	public GridBean getHostList(HostModel hostModel) {
		int page = hostModel.getPage();
		int rows = hostModel.getRows();
		int totalpage = 0;
		Long totalNum = 0l;
		Page<Host> pageObject = new Page<Host>();
		try {
			Host host =new Host();
			host.setHostStatus((byte)Status.COMMON.NORMAL.ordinal());
			host.setHostName(hostModel.getHostName());
	        PageHelper.startPage(page, rows);
			List<Host> hostList = hostMapper.selectHostList(host);
			for(Host temp: hostList){
				pageObject.add(temp);
			}
			totalpage = ((Page<?>) hostList).getPages();
			totalNum = ((Page<?>) hostList).getTotal();

		} catch (SQLException e) {
			LOGGER.error("批量查询主机失败:"+e.getMessage());
		}
		GridBean gridBean = new GridBean(page, totalpage, totalNum.intValue(), pageObject);
		return gridBean;
	}

	@Override
	public Result addToCluster(String hostId, Integer clusterId,Integer userId) {
		Result result = new Result();
		String[] hostIds = hostId.split(Constant.separator);
		//查询主机
		Cluster cluster;
		try {
			cluster = clusterMapper.getClusterDetail(clusterId);
			if(null==cluster||null==cluster.getClusterHostId()){
				LOGGER.error("集群信息查询失败");
				return new Result(false, "集群信息查询失败");
			}
		} catch (SQLException e) {
			LOGGER.error("集群信息查询失败:"+e.getMessage());
			return new Result(false, "集群信息查询失败:"+e.getMessage());
		}
		String clusterServiceIp = cluster.getServiceIp();
		//非高可用集群取集群主机IP作为服务ip
		if(cluster.getHaEnable()==Status.JUDGE.NO.ordinal()){
			String clusterHostId = cluster.getClusterHostId().split(Constant.separator)[0];
			Host clusterHost = null;
			try {
				clusterHost = hostMapper.getHostDetail(Integer.valueOf(clusterHostId));
			} catch (NumberFormatException e) {
				return new Result(false, "主机ID["+clusterHostId+"]转换异常:"+e.getMessage());
			} catch (SQLException e) {
				return new Result(false, "主机ID["+clusterHostId+"]查询异常:"+e.getMessage());
			}
			if(null==clusterHost){
				return new Result(false, "主机ID["+clusterHostId+"]不存在");
			}
			clusterServiceIp = clusterHost.getHostIp();
		}
		//判断节点是否正在运行中，如果运行中，认为是节点已被占用，防止多个集群共用。可以手动停止后加入。
		for(String hostid:hostIds){
			if(StringUtils.isEmpty(hostid)){
				continue;
			}
			result = this.nodeRunning(Integer.valueOf(hostid),cluster,userId);
			if(result.isSuccess()){
				return new Result(false,result.getMessage());
			}
		}
		//添加集群的域名到主机
		for(String hostid:hostIds){
			if(StringUtils.isEmpty(hostid)){
				continue;
			}
			//节点主机启动kube-node进程
			Host nodeHost;
			try {
				nodeHost = hostMapper.getHostDetail(Integer.valueOf(hostid));
				if(null==nodeHost){
					LOGGER.error("未查到相关节点信息");
					this.createEvent(Common.CLUSTER_ADDNODE_CHN+"["+cluster.getClusterName()+"]"+Common.FAIL_CHN, 
							Common.CLUSTER_ADDNODE_CHN, Common.FAIL_CHN, clusterId, 
							Type.EVENT_TYPE.CLUSTER.name(),userId);
					return new Result(false, "未查到相关节点信息");
				}
				if(null!=nodeHost.getClusterId()){
					this.createEvent(Common.CLUSTER_ADDNODE_CHN+"["+cluster.getClusterName()+"]"+Common.FAIL_CHN, 
							Common.CLUSTER_ADDNODE_CHN, Common.FAIL_CHN, clusterId, 
							Type.EVENT_TYPE.CLUSTER.name(),userId);
					return new Result(false, "主机已在其他集群中");
				}
			} catch (SQLException e) {
				LOGGER.error("节点主机信息查询失败:"+e.getMessage());
				this.createEvent(Common.CLUSTER_ADDNODE_CHN+"["+cluster.getClusterName()+"]"+Common.FAIL_CHN, 
						Common.CLUSTER_ADDNODE_CHN, Common.FAIL_CHN, clusterId, 
						Type.EVENT_TYPE.CLUSTER.name(),userId);
				return new Result(false, "节点主机信息查询失败:"+e.getMessage());
			}
			//更新集群master主机的域名信息到集群node主机
			result = hostCore.addDns(nodeHost.getHostIp(),clusterServiceIp, systemConfig.getKubeMasterDns());
			if(!result.isSuccess()){
				hostCore.removeDns(nodeHost.getHostIp(), systemConfig.getKubeMasterDns());
				return result;
			}
			//启动kube节点
			result = hostCore.startKube(nodeHost.getHostIp(), Type.HOST.NODE.name(),null);
			if(!result.isSuccess()){
				return result;
			}else{
				nodeHost.setClusterId(cluster.getClusterId());
				try {
					hostMapper.updateHost(nodeHost);
				} catch (SQLException e) {
					LOGGER.error("更新主机状态失败："+e.getMessage());
					this.createEvent(Common.CLUSTER_ADDNODE_CHN+"["+cluster.getClusterName()+"]"+Common.FAIL_CHN, 
							Common.CLUSTER_ADDNODE_CHN, Common.FAIL_CHN, clusterId, 
							Type.EVENT_TYPE.CLUSTER.name(),userId);
				}
			}
			//更新registry镜像仓库的地址到hosts文件
			try {
				Registry registry = registryMapper.getRegistryDetail(cluster.getClusterRegistryId());
				String registryServiceIp = registry.getServiceIp();
				if(null==registryServiceIp){
					this.createEvent(Common.CLUSTER_ADDNODE_CHN+"["+cluster.getClusterName()+"]"+Common.FAIL_CHN, 
							Common.CLUSTER_ADDNODE_CHN, Common.FAIL_CHN, clusterId, 
							Type.EVENT_TYPE.CLUSTER.name(),userId);
					return new Result(false, "主机节点配置仓库地址失败，找不到仓库服务IP");
				}
				result = hostCore.addDns(nodeHost.getHostIp(), registryServiceIp, systemConfig.getDistributionDns());
				if(!result.isSuccess()){
					this.createEvent(Common.CLUSTER_ADDNODE_CHN+"["+cluster.getClusterName()+"]"+Common.FAIL_CHN, 
							Common.CLUSTER_ADDNODE_CHN, Common.FAIL_CHN, clusterId, 
							Type.EVENT_TYPE.CLUSTER.name(),userId);
					return result;
				}
			} catch (SQLException e) {
				this.createEvent(Common.CLUSTER_ADDNODE_CHN+"["+cluster.getClusterName()+"]"+Common.FAIL_CHN, 
						Common.CLUSTER_ADDNODE_CHN, Common.FAIL_CHN, clusterId, 
						Type.EVENT_TYPE.CLUSTER.name(),userId);
			}
		}
		this.createEvent(Common.CLUSTER_ADDNODE_CHN+"["+cluster.getClusterName()+"]"+Common.SUCCESS_CHN, 
				Common.CLUSTER_ADDNODE_CHN, Common.SUCCESS_CHN, clusterId, 
				Type.EVENT_TYPE.CLUSTER.name(),userId);
		return result;
	}

	@Override
	public Result removeFromCluster(String hostId, Integer clusterId,Integer userId) {
		Result result = new Result();
		String[] hostIds = hostId.split(Constant.separator);
		//添加集群的域名到主机
		Cluster cluster;
		try {
			cluster = clusterMapper.getClusterDetail(clusterId);
			if(null==cluster||null==cluster.getClusterHostId()){
				LOGGER.error("集群信息查询失败");
				this.createEvent(Common.CLUSTER_RMNODE_CHN+"["+cluster.getClusterName()+"]"+Common.FAIL_CHN, 
						Common.CLUSTER_RMNODE_CHN, Common.FAIL_CHN, clusterId, 
						Type.EVENT_TYPE.CLUSTER.name(),userId);
				return new Result(false, "集群信息查询失败");
			}
		} catch (SQLException e) {
			LOGGER.error("集群信息查询失败:"+e.getMessage());
			return new Result(false, "集群信息查询失败:"+e.getMessage());
		}
		for(String hostid:hostIds){
			if(StringUtils.isEmpty(hostid)){
				continue;
			}
			//节点主机启动kube-node进程
			Host host;
			try {
				host = hostMapper.getHostDetail(Integer.valueOf(hostid));
				if(null==host){
					LOGGER.error("未查到相关节点信息");
					return new Result(false, "未查到相关节点信息");
				}
			} catch (SQLException e) {
				LOGGER.error("节点主机信息查询失败:"+e.getMessage());
				return new Result(false, "节点主机信息查询失败:"+e.getMessage());
			}
			String[] dns = systemConfig.getKubeMasterDns().split(Constant.separator);
			//更新集群master主机的域名信息到集群node主机
			for(int i=0;i<dns.length;i++){
				String dnsName = dns[i];
				result = hostCore.removeDns(host.getHostIp(), dnsName);
			}
			//检查是否在运行状态，如果不是运行状态，可以直接从集群中移除。否则需要停止后再移除。
			result = hostCore.nodeRunning(host.getHostIp());
			if(result.isSuccess()){
				//停止kube节点
				result = hostCore.stopKube(host.getHostIp(), Type.HOST.NODE.name());
				if(!result.isSuccess()){
					return result;
				}
			}
			try {
				//主机所属集群置空
				host.setClusterId(null);
				hostMapper.updateHost(host);
			} catch (SQLException e) {
				this.createEvent(Common.CLUSTER_RMNODE_CHN+"["+cluster.getClusterName()+"]"+Common.FAIL_CHN, 
						Common.CLUSTER_RMNODE_CHN, Common.FAIL_CHN, clusterId, 
						Type.EVENT_TYPE.CLUSTER.name(),userId);
				LOGGER.error("更新主机状态失败："+e.getMessage());
			}
		}
		this.createEvent(Common.CLUSTER_RMNODE_CHN+"["+cluster.getClusterName()+"]"+Common.SUCCESS_CHN, 
				Common.CLUSTER_RMNODE_CHN, Common.SUCCESS_CHN, clusterId, 
				Type.EVENT_TYPE.CLUSTER.name(),userId);
		return result;
	}
	/**
	* @Title: isHostExist 
	* @Description: 主机是否已经存在
	* @param @param hostIp
	* @param @return    设定文件 
	* @return boolean    返回类型 
	* @throws
	 */
	public boolean isHostExist(String hostIp){
		try {
			Host host =new Host();
			host.setHostIp(hostIp);
			host.setHostStatus((byte)Status.COMMON.NORMAL.ordinal());
			List<Host> hosts = hostMapper.selectHostList(host);
			if(hosts.isEmpty()){
				return false;
			}else{
				return true;
			}
		} catch (SQLException e) {
			return false;
		}
	}

	@Override
	public Result unUsedHost(Host host) {
		Result result = new Result();
		try {
			host.setHostStatus((byte)Status.COMMON.NORMAL.ordinal());
			List<Host> hosts = hostMapper.selectHostList(host);
			Iterator<Host> iterator = hosts.iterator();
			while(iterator.hasNext()){
				if(iterator.next().getClusterId()!=null){
					iterator.remove();
				}
			}
			result = new Result(true, hosts, "success");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}

	@Override
	public Result clusterHosts(Host host) {
		Result result = new Result();
		try {
			host.setHostStatus((byte)Status.COMMON.NORMAL.ordinal());
			host.setHostType((byte)Type.HOST.NODE.ordinal());
			List<Host> hosts = hostMapper.selectHostList(host);
			result = new Result(true, hosts, "success");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
	/**
	 * 
	* @Title: createTaskEvent 
	* @Description: 任务执行事件 
	* @param     设定文件 
	* @return void    返回类型 
	* @throws
	 */
	private void createEvent(String eventDesc, String eventName,String eventResult, 
			Integer eventObjectID,String eventType,Integer eventCreator){
		Event event = new Event(eventDesc, eventName, eventResult,eventObjectID, eventType,eventCreator);
		eventMapper.insertEnv(event);
	}
	/**
	 * mayunhao
	* @Title: checkNodeKube 
	* @Description: 检查节点kube进程是否启动
	* @param @param hostIds
	* @param @param cluster
	* @param @param userId
	* @param @return    设定文件 
	* @return Result    返回类型 
	* @throws
	 */
	private Result nodeRunning(Integer hostid, Cluster cluster, Integer userId) {
		if(null==hostid){
			return new Result(false, "请选择添加主机");
		}
		//节点主机启动kube-node进程
		Host nodeHost;
		try {
			nodeHost = hostMapper.getHostDetail(hostid);
			if(null==nodeHost){
				LOGGER.error("未查到相关节点信息");
				this.createEvent(Common.CLUSTER_ADDNODE_CHN+"["+cluster.getClusterName()+"]"+Common.FAIL_CHN, 
						Common.CLUSTER_ADDNODE_CHN, Common.FAIL_CHN, cluster.getClusterId(), 
						Type.EVENT_TYPE.CLUSTER.name(),userId);
				return new Result(false, "未查到相关节点信息");
			}
			if(null!=nodeHost.getClusterId()){
				this.createEvent(Common.CLUSTER_ADDNODE_CHN+"["+cluster.getClusterName()+"]"+Common.FAIL_CHN, 
						Common.CLUSTER_ADDNODE_CHN, Common.FAIL_CHN, cluster.getClusterId(), 
						Type.EVENT_TYPE.CLUSTER.name(),userId);
				return new Result(false, "主机已在其他集群中");
			}
		} catch (SQLException e) {
			LOGGER.error("节点主机信息查询失败:"+e.getMessage());
			this.createEvent(Common.CLUSTER_ADDNODE_CHN+"["+cluster.getClusterName()+"]"+Common.FAIL_CHN, 
					Common.CLUSTER_ADDNODE_CHN, Common.FAIL_CHN, cluster.getClusterId(), 
					Type.EVENT_TYPE.CLUSTER.name(),userId);
			return new Result(false, "节点主机信息查询失败:"+e.getMessage());
		}
		//检查主机kubernetes进程是否已经启动
		Result result = hostCore.nodeRunning(nodeHost.getHostIp());
		if(result.isSuccess()){
			return new Result(true, "主机["+nodeHost.getHostIp()+"] node进程已经在运行，不能添加到新的集群");
		}else{
			return result;
		}
		
	}

	@Override
	public JSONObject hostBoard() {
		try {
			Host host = new Host();
			host.setHostStatus((byte)Status.HOST.ONLINE.ordinal());
			List<Host> onlineHosts = hostMapper.selectHostList(host);
			host.setHostStatus((byte)Status.HOST.OFF.ordinal());
			List<Host> offlineHosts = hostMapper.selectHostList(host);
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("host_total", onlineHosts.size()+offlineHosts.size());
			jsonObject.put("host_online", onlineHosts.size());
			jsonObject.put("host_offline", offlineHosts.size());
			return jsonObject;
		} catch (SQLException e) {
			LOGGER.error("主机信息查询失败："+e.getMessage());
			return new JSONObject();
		}
	}
}
